/* user.c : User processes
 */

#include <kernel.h>
#include <i386.h>
#define OUT_SZ 1024

//void sleeper1(void);
//void sleeper2(void);


/*
 * Extended Consumer
**/

//void consumerx(void);

// root process id
int root_pid;

void signaller(void){
	int rc;
	char out[OUT_SZ];
	syssleep(100);
	sysputs("Sending signal 20\n");
	rc = syskill(100, 20);
	sprintf(out, "Signal 20 rc: %d\nSending signal 0\n", rc);
	sysputs(out);
	rc = syskill(100, 18);
	sprintf(out, "Signal 18 rc: %d\n", rc);
	sysputs(out);
}

void signal_handler(){
    sysputs("Got signal 18!\n");
}


extern void root(void){

    /*
    char buf[256];
    char out[256];
    
    sysputs("Hello, world!\n");
    
    int fd = sysopen(DEVICE_ECHOKBD);
    kprintf("Opened kbd = %d\n", fd);
    sysputs("Before sysread\n");
    int ret = sysread(fd, buf, 10);
    sysputs("Back in root!\n");
    sprintf(out, "sysread() = %d\n", ret);
    sysputs(out);
    
    ret = sysread(fd, buf, 10);
    sysputs("Back in root!\n");
    sprintf(out, "sysread() = %d\n", ret);
    sysputs(out);
    
    sysputs("After sysread\n");
    //sprintf(out, "Read %d bytes = %s\n", ret, buf);
        
    //sysclose(fd);

    while(1);
	*/

    
    int fd1, fd2, ret;
    char buf[256];
    char out[OUT_SZ];
    

    sysputs("Hello, world!\n\n");
    
    fd1 = sysopen(DEVICE_ECHOKBD);
    
    sprintf(out, "Opened echo fd = %d\n", fd1);
    sysputs(out);
    
    size_t i;
    for(i = 0; i < 10; i++){
        sysputs("Read 1 char: ");
        ret = sysread(fd1, buf, 1);
        sprintf(out, "Read %s, ret = %d\n", buf, ret);
        sysputs(out);
    }
    
    fd2 = sysopen(DEVICE_KBD);
    
    sprintf(out, "Open no-echo fd = %d\n", fd2);
    sysputs(out);
    
    sysclose(fd2);
    
    fd2 = sysopen(DEVICE_ECHOKBD);
    
    sprintf(out, "(Re)open echo fd = %d\n", fd2); 
    sysputs(out);
    
    sysclose(fd1);
    
    fd1 = sysopen(DEVICE_KBD);
    
    for(i = 0; i < 3; i++){
        sysputs("Read a line: ");
        sysread(fd1, buf, 15);
        sysputs(buf);
        bzero(buf, 256);
    }
    
    while(1){
        sysputs("Type CTRL-D: ");
        ret = sysread(fd1, buf, 10);
        if(ret <= 0)
            break;
    }
    
    sysclose(fd1);
    
    sysputs("Open echo kbd\n");
    fd1 = sysopen(DEVICE_ECHOKBD);
    
    syssighandler(18, signal_handler);
    sysputs("Installed signal 18 handler\n");

    syscreate(signaller, 4096);	
    
    sysputs("Attempting sysread()...\n");
    ret = sysread(fd1, buf, 10);
    sprintf(out, "sysread() returned %d\n", ret);
    sysputs(out);
    
    while(1){
        sysputs("Type CTRL-D: ");
        ret = sysread(fd1, buf, 10);
        if(ret <= 0)
            break;
    }
    
    sysputs("Read EOF, attempting last read...\n");
    
    ret = sysread(fd1, buf, 10);
    
    sprintf(out, "Last read return %d\n", ret);
    sysputs(out);
    
    
    sysputs("All done. KThxBye.");

    // loop infinitely
    while(1);
    
    
    /*
	int rc;
	char out[OUT_SZ];
	rc = syssighandler(0, sh_lowp);
	syscreate(signaller, 4096);				
	void* buf = kmalloc(4096);
	int* from = 0;
	syssend(*from, buf, 4096);
	sprintf(out, "Root rc was %d\n", rc);
	sysputs(out);
	*/ 
}



/*
 * The idle process
 * It idles.
**/
extern void idle(void){
	while(TRUE){
		// TODO: hlt
	}
}


/*
ASSIGNMENT 2 PRODUCER AND CONSUMER:

--------------------------------------

extern void root(void){
	
	
	
	int pid[4];
	int msg, res, me;
	char out[OUT_SZ];
	
	root_pid = sysgetpid();
	
	bzero(out, OUT_SZ);
	sprintf(out, "Process %d (root) is alive.\n", root_pid);
	sysputs(out);

	
	
	int i;
	// create consumer processes
	for(i = 0; i < 4; i++){
		pid[i] = syscreate(consumerx, STDSTACKSIZ);
		
		bzero(out, OUT_SZ);
		sprintf(out, "Process %d (root) created process %d of 4: %d\n", root_pid, (i+1), pid[i]);
		sysputs(out);
	}
	
	syssleep(4000);
	
	// send out sleep times
	msg = 10*1000;
	syssend(pid[2], &msg, sizeof(int));
	
	msg = 7*1000;
	syssend(pid[1], &msg, sizeof(int));
	
	msg = 20*1000;
	syssend(pid[0], &msg, sizeof(int));
	
	msg = 27*1000;
	syssend(pid[3], &msg, sizeof(int));
	
	// this should fail
	res = sysrecv(&pid[3], &msg, sizeof(int));
	
	
	bzero(out, OUT_SZ);
	sprintf(out, "Process %d (root) sysrecv() returned %d\n", root_pid, res);
	sysputs(out);
	
	
}

void consumerx(void){
	int me;
	int pid;
	int msg;
	int res;
	char out[OUT_SZ];
	
	me = sysgetpid();
	
	bzero(out, OUT_SZ);
	sprintf(out, "Process %d is alive.\n", me);
	sysputs(out);
	
	
	syssleep(5000);
	
	// get my sleep time
	res = sysrecv(&root_pid, &msg, sizeof(int));
	
	if(res == -1){
		
		bzero(out, OUT_SZ);
		sprintf(out, "Process %d sysrecv() returned -1\n", me);
		sysputs(out);
		return;
	}
	

	bzero(out, OUT_SZ);
	sprintf(out, "Process %d message received, sleeping for %dms\n", me, msg);
	sysputs(out);
	
	// sleep for the requested duration
	syssleep(msg);
	
	
	bzero(out, OUT_SZ);
	sprintf(out, "Process %d sleeping complete, exiting...\n", me);
	sysputs(out);	 
}
--------------------------------------------
END ASSIGNMENT 2 PRODUCER AND CONSUMER
*/


/*
void sleeper1(void){
	int i = 0;
	
	kprintf("Sleeper1 is process %d\n", sysgetpid());
	
	while(1){
		i++;
		kprintf("Sleeper1 - %d\n", (i++));
		syssleep(20000);
		
	}	
	
}

void sleeper2(void){
	int i = 0;
	
	kprintf("Sleeper2 is process %d\n", sysgetpid());
	
	while(1){
		i++;
		kprintf("Sleeper2 - %d\n", (i++));
		syssleep(20000);
		
	}
}
*/
